﻿// copyright (c) 2025 author:fio66<fio66@foxmail.com>. All rights reserved.
// date: 2025-08-19 14:35:58

#include <windows.h>
#include <string>

#include "logger/logger.hpp"
#include "include/cef_command_line.h"
#include "include/cef_sandbox_win.h"
#include "include/cef_version_info.h"

#include "src/manager/audio_player_manager.h"


namespace {

int RunMain(HINSTANCE hInstance,
            LPTSTR lpCmdLine,
            int nCmdShow,
            void* sandbox_info) {
  int exit_code;

  // Initialize logger
  fio66::Logger::Initialize("audio_player");
  
  // 演示日志级别控制
  fio66::Logger::SetLogLevel(google::GLOG_INFO);
  
  // 提供CEF命令行参数
  CefMainArgs main_args(hInstance);

  // CEF applications have multiple sub-processes (render, GPU, etc) that share
  // the same executable. This function checks the command-line and, if this is
  // a sub-process, executes the appropriate logic.
  exit_code = CefExecuteProcess(main_args, nullptr, sandbox_info);
  if (exit_code >= 0) {
    // The sub-process has completed so return here.
    return exit_code;
  }

  // Parse command-line arguments for use in this method.
  CefRefPtr<CefCommandLine> command_line = CefCommandLine::CreateCommandLine();
  command_line->InitFromString(::GetCommandLineW());

  // Specify CEF global settings here.
  CefSettings settings;

  if (!sandbox_info) {
    settings.no_sandbox = true;
  }

  // AudioPlayerApp implements application-level callbacks for the browser process.
  // It will create the first browser instance in OnContextInitialized() after
  // CEF has initialized.
  fio66::AudioPlayerManager manager;


  // Initialize the CEF browser process. May return false if initialization
  // fails or if early exit is desired (for example, due to process singleton
  // relaunch behavior).
  if (!CefInitialize(main_args, settings, manager.GetApp(), sandbox_info)) {
    return CefGetExitCode();
  }

  // Run the CEF message loop. This will block until CefQuitMessageLoop() is
  // called.
  CefRunMessageLoop();

  // Shut down CEF.
  CefShutdown();

  // Log application exit
  LOGI << "Application shutting down";
  fio66::Logger::Shutdown();

  return 0;
}

}  // namespace

#if defined(CEF_USE_BOOTSTRAP)

// 确保g_exe_instance在使用bootstrap时也有定义
HINSTANCE g_exe_instance;

// Entry point called by bootstrap.exe when built as a DLL.
CEF_BOOTSTRAP_EXPORT int RunWinMain(HINSTANCE hInstance,
  LPTSTR lpCmdLine,
  int nCmdShow,
  void* sandbox_info,
  cef_version_info_t* /*version_info*/) {
  g_exe_instance = hInstance;
  return ::RunMain(hInstance, lpCmdLine, nCmdShow, sandbox_info);
}

#else  // !defined(CEF_USE_BOOTSTRAP)
HINSTANCE g_exe_instance;
// Entry point function for all processes.
int APIENTRY wWinMain(HINSTANCE hInstance,
  HINSTANCE hPrevInstance,
  LPTSTR lpCmdLine,
  int nCmdShow) {
  UNREFERENCED_PARAMETER(hPrevInstance);
  UNREFERENCED_PARAMETER(lpCmdLine);
  g_exe_instance = hInstance;
#if defined(ARCH_CPU_32_BITS)
  // Run the main thread on 32-bit Windows using a fiber with the preferred 4MiB
  // stack size. This function must be called at the top of the executable entry
  // point function (`main()` or `wWinMain()`). It is used in combination with
  // the initial stack size of 0.5MiB configured via the `/STACK:0x80000` linker
  // flag on executable targets. This saves significant memory on threads (like
  // those in the Windows thread pool, and others) whose stack size can only be
  // controlled via the linker flag.
  int exit_code = CefRunWinMainWithPreferredStackSize(wWinMain, hInstance,
    lpCmdLine, nCmdShow);
  if (exit_code >= 0) {
    // The fiber has completed so return here.
    return exit_code;
  }
#endif

  void* sandbox_info = nullptr;

#if defined(CEF_USE_SANDBOX)
  // Manage the life span of the sandbox information object. This is necessary
  // for sandbox support on Windows. See cef_sandbox_win.h for complete details.
  CefScopedSandboxInfo scoped_sandbox;
  sandbox_info = scoped_sandbox.sandbox_info();
#endif

  return ::RunMain(hInstance, lpCmdLine, nCmdShow, sandbox_info);
}

#endif  // !defined(CEF_USE_BOOTSTRAP)
